package cn.alpha.workflow.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cn.alpha.common.utils.WorkflowUtils;

/**
 * 工作流跟踪相关Service
 * @author HenryYan
 */
@Component
public class WorkflowTraceService {
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    protected RuntimeService runtimeService;

    @Autowired
    protected TaskService taskService;

    @Autowired
    protected RepositoryService repositoryService;

    @Autowired
    protected IdentityService identityService;

    @Autowired
    protected HistoryService historyService;
    
    /**流程跟踪图*/
    public List<Map<String, Object>> traceProcess(String procinstId) throws Exception 
    {
        String activityId = null;
        String procdefId;
        ProcessInstance procinst = runtimeService.createProcessInstanceQuery().processInstanceId(procinstId).singleResult();
        if(procinst==null)
        {	
        	HistoricProcessInstance procinstH=historyService.createHistoricProcessInstanceQuery().processInstanceId(procinstId).singleResult();
        	procdefId=procinstH.getProcessDefinitionId();
        }
        else
        {
        	procdefId=procinst.getProcessDefinitionId();
        	Execution execution = runtimeService.createExecutionQuery().executionId(procinstId).singleResult();//执行实例
            Object property = PropertyUtils.getProperty(execution, "activityId");
            if (property != null) 
                activityId = property.toString();
        }
        
        ProcessDefinitionEntity processDefinition= (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(procdefId);
        List<ActivityImpl> activitiList = processDefinition.getActivities();//获得当前任务的所有节点
        List<Map<String, Object>> activityInfos = new ArrayList<Map<String, Object>>();
        for (ActivityImpl activity : activitiList) 
        {
            String id = activity.getId();
            Map<String, Object> activityImageInfo = packageSingleActivitiInfo(activity, procinstId,id.equals(activityId)?activityId:null);
            activityInfos.add(activityImageInfo);
        }

        return activityInfos;
    }

    /**封装输出信息，包括：当前节点的X、Y坐标、变量信息、任务类型、任务描述*/
    private Map<String, Object> packageSingleActivitiInfo(ActivityImpl activity, String procinstId, String curActivitiId) throws Exception 
    {
        Map<String, Object> vars = new HashMap<String, Object>();
        Map<String, Object> activityInfo = new HashMap<String, Object>();
        activityInfo.put("currentActiviti", curActivitiId!=null);
        setPosition(activity, activityInfo);
        setWidthAndHeight(activity, activityInfo);

        Map<String, Object> properties = activity.getProperties();
        vars.put("任务类型", WorkflowUtils.parseToZhType(properties.get("type").toString()));

        ActivityBehavior activityBehavior = activity.getActivityBehavior();
        logger.debug("activityBehavior={}", activityBehavior);
        if (activityBehavior instanceof UserTaskActivityBehavior) 
        {
            Task currentTask = null;
			//当前节点的task
            if (curActivitiId!=null) 
                currentTask = taskService.createTaskQuery().processInstanceId(procinstId)
                		.taskDefinitionKey(curActivitiId).singleResult();

			//当前任务的分配角色
            UserTaskActivityBehavior userTaskActivityBehavior = (UserTaskActivityBehavior) activityBehavior;
            TaskDefinition taskDefinition = userTaskActivityBehavior.getTaskDefinition();
            Set<Expression> candidateGroupIdExpressions = taskDefinition.getCandidateGroupIdExpressions();
            if (!candidateGroupIdExpressions.isEmpty()) 
            {
                // 任务的处理角色
                setTaskGroup(procinstId,vars, candidateGroupIdExpressions);

                // 当前处理人
                if (currentTask != null) 
                    setCurrentTaskAssignee(vars, currentTask);
            }
        }

        vars.put("节点说明", properties.get("documentation"));
        vars.put("描述", activity.getProcessDefinition().getDescription());

        logger.debug("trace variables: {}", vars);
        activityInfo.put("vars", vars);
        return activityInfo;
    }

    private void setTaskGroup(String procinstId,Map<String, Object> vars, Set<Expression> candidateGroupIdExpressions) 
    {
        String roles = "";
        String roleName;
        Group group;
        for (Expression expression : candidateGroupIdExpressions) 
        {
            String expressionText = expression.getExpressionText();
            roleName="";
            group=identityService.createGroupQuery().groupId(expressionText).singleResult();
            if(group==null)
            {
            	expressionText=getVarValue(procinstId,expressionText);
            	if(expressionText!=null)
            		group=identityService.createGroupQuery().groupId(expressionText).singleResult();
            }
            if(group!=null)
            	roleName = group.getName();
            
            roles += roleName;
        }
        vars.put("任务所属角色", roles);
    }

    private String getVarValue(String procinstId,String expression)
    {
    	if(StringUtils.isEmpty(expression)||expression.length()<3)
    		return null;
    	
    	HistoricVariableInstance var=historyService.createHistoricVariableInstanceQuery()
    		.variableName(expression.substring(2, expression.length()-1)).processInstanceId(procinstId).singleResult();
    	return var==null?null:var.getValue().toString();
    }
    
    
    /**设置当前处理人信息 */
    private void setCurrentTaskAssignee(Map<String, Object> vars, Task currentTask) 
    {
        String assignee = currentTask.getAssignee();
        if (assignee == null)
        	return;

        User assigneeUser = identityService.createUserQuery().userId(assignee).singleResult();
        String userInfo = assigneeUser.getFirstName() + " " + assigneeUser.getLastName();
        vars.put("当前处理人", userInfo);
    }

    /*** 设置宽度、高度属性*/
    private void setWidthAndHeight(ActivityImpl activity, Map<String, Object> activityInfo) 
    {
        activityInfo.put("width", activity.getWidth());
        activityInfo.put("height", activity.getHeight());
    }

    /**设置坐标位置*/
    private void setPosition(ActivityImpl activity, Map<String, Object> activityInfo) 
    {
        activityInfo.put("x", activity.getX());
        activityInfo.put("y", activity.getY());
    }
}
